
package jp.ize.ux.tween;

// {{{ imports
import flash.events.Event;
import flash.events.EventDispatcher;
import jp.ize.ux.tween.UXTween;
import jp.ize.iwp.RuntimeEngine;
// }}}
// {{{ class UXTweenList
/**
 * UXTweenのリストです。繰り返し状態やアクティブ状態を保持します。
 */
class UXTweenList
{
	// {{{ properties
	// {{{ public var loop:Bool;
	/**
	* 繰り返しを行なうかどうかを保持します。デフォルトは false です。
	*/
	public var loop:Bool;
	// }}}
	// {{{ public var active:Bool;
	/**
	* 現在アクティブ状態かどうかを保持します。デフォルトは false です。
	*/
	public var active:Bool;
	// }}}
	// {{{ public var list:Array<UXTween<Dynamic,Dynamic>>;
	/**
	* UXTween のリストを保持します。UXTweenManagerによって管理されます。
	*/
	public var list:Array<UXTween<Dynamic,Dynamic>>;
	// }}}
	// }}}
	// {{{ public function new() : Void
	/**
	* コンストラクタ
	*/
	public function new() : Void
	{
		loop   = false;
		active = false;
		list   = new Array();
	}

	// }}}
}
// }}}
// {{{ class UXTweenManager
/**
 * UXTween の排他制御やトゥイーンの繰り返し、複数トゥイーンの連続実行等を行なうための管理クラスです。
 */
class UXTweenManager
{
	// {{{ properties
	// {{{ public var objects:Hash<Dynamic>;
	/**
	* トゥイーンの対象となるオブジェクトのリストです。ID識別子を付けて管理します。
	*/
	public var objects:Hash<Dynamic>;
	// }}}
	// {{{ public var tweens:Hash<UXTweenList>;
	/**
	* UXTweenList の集合です。
	*/
	public var tweens:Hash<UXTweenList>;
	// }}}
	// }}}
	// {{{ public function new() : Void
	/**
	* コンストラクタ
	*/
	public function new() : Void
	{
		objects = new Hash();
		tweens  = new Hash();
	}

	// }}}
	// {{{ public function registObject( id:String, obj:Dynamic )
	/**
	* トゥイーンの対象となるオブジェクトを ID を付けて登録します。
	*/
	public function registObject( id:String, obj:Dynamic )
	{
		objects.set( id, obj );
		tweens.set( id, new UXTweenList() );
	}

	// }}}
	// {{{ public function addTweenChain( id:String, tw:UXTween<Dynamic,Dynamic>, ?end:Dynamic->Void  ) : Void
	/**
	* トゥイーンをオブジェクトIDによって管理します。
	* 複数同時実行してしまうと矛盾が起きたりするトゥイーンをIDで管理することによって排他制御を行います。
	* もしくは、順番を守って実行したいトゥイーンなどを同IDを使って登録します。
	*/
	public function addTweenChain( id:String, tw:UXTween<Dynamic,Dynamic>, ?end:Dynamic->Void  ) : Void
	{
		if ( objects.exists(id) ) {
			var obj = objects.get(id);
			var me = this;
			var endFunc = tw.getEndTweenHandler();
			tw.setEndTweenHandler( function(x){
				if ( endFunc!=null ) endFunc(x);
				if ( end!=null ) end(x);
				if ( me.tweens.exists(id) ) {
					var uxtl:UXTweenList = me.tweens.get(id);
					var tlist = uxtl.list;
					//trace(uxtl.active);
					if ( tlist.length>0 ) {
						var tween = tlist.shift();
						tween.start();
						if ( uxtl.loop ) {
							tlist.push( tween );
							//me.tweens.set(id,tlist);
						}
					} else {
						uxtl.active = false;
					}
				}
			});
			var uxtl = null;
			if ( tweens.exists(id) ) {
				uxtl = tweens.get(id);
			} else {
				uxtl = new UXTweenList();
			}
			uxtl.list.push(tw);
			//trace("push: (" + id + ") " + uxtl.list.length);
			tweens.set( id, uxtl );
		}
	}

	// }}}
	// {{{ public function start( ?id:String, ?isLoop:Bool, ?base:EventDispatcher ) : Void
	/**
	* 登録されているIDのトゥイーン・チェインを実行します。
	* IDを省略した場合は、すべてのトゥイーン・チェインを実行します。
	* 繰り返し実行するかどうかは isLoopFlag で指定します。
	* isLoopFlag を指定しなかった場合は false で繰り返しを行ないません。
	*/
	public function start( ?id:String, ?isLoopFlag:Bool, ?base:EventDispatcher ) : Void
	{
		if ( isLoopFlag==null ) isLoopFlag = false;
		if ( id!=null ) {
			if ( tweens.exists(id) ) {
				var uxtl:UXTweenList = tweens.get(id);
				uxtl.loop = isLoopFlag;
				if ( uxtl.list.length>0 && !uxtl.active ) {
					var tween = uxtl.list.shift();
					//trace("start: (" + id + ") " + uxtl.list.length);
					tween.start( base );
					uxtl.active = true;
					if ( isLoopFlag ) {
						uxtl.list.push( tween );
						tweens.set( id, uxtl );
					}
				}
			}
		} else {
			for ( id in tweens.keys() ) {
				var uxtl:UXTweenList = tweens.get(id);
				uxtl.loop = isLoopFlag;
				//trace(uxtl.list.length);
				if ( uxtl.list.length>0 && !uxtl.active ) {
					var tween = uxtl.list.shift();
					//trace("start: (" + id + ") " + uxtl.list.length);
					tween.start( base );
					uxtl.active = true;
					if ( isLoopFlag ) {
						uxtl.list.push( tween );
						tweens.set( id, uxtl );
					}
				}
			}
		}
	}

	// }}}
}
